/******************************************************************************

  Copyright (C), 2020-2025, HiFace Tech. Co., Ltd.

  HiFace Camera Interface  (HCI)
  HiFace Camera Module  (HCM)

以下四个函数接口必须存在，以主应用先关联
  HCM_USRPLATFORM_Init
  HCM_USRPLATFORM_UnInit
  HCM_USRPLATFORM_DealAiNalyseData
  HCM_USRPLATFORM_GetInfo

******************************************************************************/

#include <errno.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>

#include "hci_def.h"
#include "hci_intf.h"
#include "hci_struct.h"
#include "hcmComInfo.h"

#define OK 0UL
#define ERR 1UL
#define PORT 18500
#define BUF_SIZE 7

CHAR *pVersion = "usrplatform v1.0.0";
HCI_FUNC *gpHciFunc = NULL;

void *thread_uart();

// 主进程起来会去调用 HCM_USRPLATFORM_Init
// 注意此函数不能阻塞, 用户可以开启线程方式来初始化
// 可以通过pstHcFunc 来获取设备相关信息接口
INT HCM_USRPLATFORM_Init(HCI_FUNC *pstHcFunc)
{
    gpHciFunc = pstHcFunc;

    // pthread_t thread_id; // 线程ID
    // printf("主线程开始执行。\n");

    // // 创建线程
    // if (pthread_create(&thread_id, NULL, thread_uart, NULL) != 0) {
    //     perror("无法创建线程");
    //     return 1;
    // }

    // // 等待线程结束
    // pthread_detach(thread_id);
    // printf("主线程结束执行。\n");
    // return 0;

    return 0;
}

INT HCM_USRPLATFORM_UnInit(VOID)
{
    printf("HCM_USRPLATFORM_UnInit...\n");
    gpHciFunc = NULL;
    return 0;
}

CHAR *HCM_USRPLATFORM_GetInfo(VOID) { return pVersion; }

void *thread_uart()
{
    HCM_UART_INFO_S stUart_Config;
    stUart_Config.baudrate = 9600;
    stUart_Config.datawidth = 8;
    stUart_Config.parity = 'N';
    stUart_Config.stopbit = 1;
    stUart_Config.RS485 = 1;

    const uint8_t uart_chn = 1;

    gpHciFunc->Intf_UartCreate(uart_chn);
    gpHciFunc->Intf_UartConfig(uart_chn, &stUart_Config);

    int sockfd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t sin_size;
    uint8_t buffer[BUF_SIZE] = {0};
    sin_size = sizeof(struct sockaddr_in);

    // 创建socket文件描述符
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 填充服务器信息
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);

    // 绑定socket到服务器地址
    if (bind(sockfd, (const struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    while (1)
    {
        // 接收客户端数据
        if (recvfrom(sockfd, buffer, BUF_SIZE, 0, (struct sockaddr *)&client_addr, &sin_size) == -1)
        {
            perror("recvfrom failed");
            exit(EXIT_FAILURE);
        }

        gpHciFunc->Intf_UartWriteData(uart_chn, buffer, BUF_SIZE);

        memset(buffer, 0x00, BUF_SIZE);

        gpHciFunc->Intf_UartReadData(uart_chn, buffer, BUF_SIZE, 100 * 1000);

        // 将接收到的数据原样返回给客户端
        if (sendto(sockfd, buffer, BUF_SIZE, 0, (const struct sockaddr *)&client_addr, sin_size) ==
            -1)
        {
            perror("sendto failed");
            exit(EXIT_FAILURE);
        }

        // 清空缓冲区，准备接收下一组数据
        memset(buffer, 0, BUF_SIZE);
    }

    // 关闭socket
    close(sockfd);

    return 0;
}

void OSD_test()
{
    HCM_OSD_S osd_cfg;
    gpHciFunc->Intf_GetParam(HCI_CFG_OSD, 0, &osd_cfg, sizeof(osd_cfg));
    osd_cfg.stBmpLogoOSD.nBmpx = 300;
    osd_cfg.stBmpLogoOSD.nBmpy = 300;
    osd_cfg.stBmpLogoOSD.nUpdatePicFlag = 1;
    osd_cfg.stBmpLogoOSD.nBmpEnable = 1;

    osd_cfg.stBmpLogoOSDtherChn.nBmpx = 300;
    osd_cfg.stBmpLogoOSDtherChn.nBmpy = 300;
    osd_cfg.stBmpLogoOSDtherChn.nUpdatePicFlag = 1;
    osd_cfg.stBmpLogoOSDtherChn.nBmpEnable = 1;
    osd_cfg.bZoomOSD = 12;

    gpHciFunc->Intf_SetParam(HCI_CFG_OSD, 0, &osd_cfg, sizeof(osd_cfg));
}